package com.jiashihui.schema_lgorithm.java.basics;

import java.sql.Date;

/**
 * @author jiashihui
 * @describe: static
 * @date 2019/03/25
 *
 * static表示“全局”或者“静态”的意思，用来修饰成员变量和成员方法，当然也可以修饰代码块
 *
 * Java把内存分为栈内存和堆内存，其中栈内存用来存放一些基本类型的变量、数组和对象的引用，堆内存主要存放一些对象。
 * 在JVM加载一个类的时候，若该类存在static修饰的成员变量和成员方法，则会为这些成员变量和成员方法在固定的位置开辟一个固定大小的内存区域，
 * 同时被static修饰的成员变量和成员方法是独立于该类的，它不依赖于某个特定的实例变量，也就是说它被该类的所有实例共享。所有实例的引用都指向同一个地方，任何一个实例对其的修改都会导致其他实例的变化。
 *
 * 静态变量是随着类加载时被完成初始化的，它在内存中仅有一个，且JVM也只会为它分配一次内存，同时类所有的实例都共享静态变量，可以直接通过类名来访问它。
 * 但是实例变量则不同，它是伴随着实例的，每创建一个实例就会产生一个实例变量，它与该实例同生共死。
 *
 * 1、static变量
 * 两种情况下使用静态变量：对象之间共享数据、访问方便。
 * 2、static方法
 * static方法一般称作静态方法，由于静态方法不依赖于任何对象就可以进行访问，因此对于静态方法来说，是没有this的，因为它不依附于任何对象，既然都没有对象，就谈不上this了。并且由于这个特性，在静态方法中不能访问类的非静态成员变量和非静态成员方法，因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
 * 但是要注意的是，虽然在静态方法中不能访问非静态成员方法和非静态成员变量，但是在非静态成员方法中是可以访问静态成员方法/变量的。
 * 因为static方法独立于任何实例，因此static方法必须被实现，而不能是抽象的abstract。
 * 3、static代码块
 * static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。
 *
 * 1、static关键字会改变类中成员的访问权限吗？
 * Java中的static关键字不会影响到变量或者方法的作用域。在Java中能够影响到访问权限的只有private、public、protected（包括包访问权限）这几个关键字。
 * 2、能通过this访问静态成员变量吗？
 * 静态成员变量虽然独立于对象，但是不代表不可以通过对象去访问，所有的静态方法和静态变量都可以通过对象访问。
 * 3、static能作用于局部变量么？
 * 在Java中切记：static是不允许用来修饰局部变量。
 * 4、static和final一块用表示什么？
 * static final用来修饰成员变量和成员方法，可简单理解为“全局常量”！
 * 对于变量，表示一旦给值就不可修改，并且通过类名可以访问。
 * 对于方法，表示不可覆盖，并且可以通过类名直接访问。
 *
 * ********生成对象的时候（初始化成员变量），必须先初始化父类的成员变量。********
 * 对象的初始化顺序: 静态代码块内容先执行，接着执行父类非静态代码块和构造方法，然后执行子类非静态代码块和构造方法。
 * 注意:子类的构造方法，不管这个构造方法带不带参数，默认的它都会先去寻找父类的不带参数的构造方法。如果父类没有不带参数的构造方法，那么子类必须用supper关键子来调用父类带参数的构造方法，否则编译不能通过。
 */
public class StaticTest {
    private Date birthDate;
    private static Date startDate,endDate;
    // 很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
    static{
        startDate = Date.valueOf("1946");
        endDate = Date.valueOf("1964");
    }
    public StaticTest(Date birthDate) {
        this.birthDate = birthDate;
    }
    boolean isBornBoomer() {
        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
    }

    private static int userNumber  = 0 ;
    public StaticTest(){
        userNumber++;
    }

    public static void main(String[] args) {
        StaticTest t1 = new StaticTest();
        StaticTest t2 = new StaticTest();

        System.out.println("t1 userNumber：" + t1.userNumber);
        System.out.println("t2 userNumber：" + t2.userNumber);
    }
}
